package com.small.handler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;

import com.small.annotation.Controller;
import com.small.context.Context;
import com.small.utils.BaseUtil;

import net.sf.json.JSONObject;

/**核心请求处理类 提高Linux、Windows通用
 * @author 乐乐
 */
public class DispatcherHandle {
  private static final Logger logger = Logger.getLogger(DispatcherHandle.class);

  /**
   * 动态请求处理  根据请求规则进行请求分发
   * @param req
   * @param resp
   * @param context
   */
  public void dynamicRequest(HttpServletRequest req, HttpServletResponse resp, Context context) throws Exception {
      context.setHttpServletRequest(req);
      context.setHttpServletResponse(resp);
      // 获取请求的URI地址信息
      String url = req.getRequestURI();
      //获取项目名
      String platform = req.getServletContext().getContextPath();
      //文件分隔符问题
      platform = BaseUtil.pathSeparator(platform);
      url = BaseUtil.pathSeparator(url);
      
      //根据HttpRequest获取请求类型，是否携带文件 获取请求参数
      if(ClassHelper.getRequestType(req, context).equals("Json")){
          //普通请求获取请求参数并设置全局请求参数中
          JSONObject data = ClassHelper.getAllRequestParam(req, context);
          if (null != data)
              context.setParameter(data);
      }else if (ClassHelper.getRequestType(req, context).equals("File")){
          //携带文件的请求获取文件并转为输入流加入上下文全局集合流中，请求中的普通字段加入parameter中
          List<InputStream> inputStreams = null;
          try {
              inputStreams = ClassHelper.getInputStream(req, context);
          }catch (Exception e){
              logger.error(e.toString());
          }
          if (null != inputStreams)
              context.setInputStreams(inputStreams);
      }

      //获取路由 类路径和方法名
      Map<String, String> map = ClassHelper.annotation(url, platform);
      String annotation = "";
      String method = "";
      try {
          annotation = map.get("annotation").toString().substring(1);
          method = (String) map.get("method");
      }catch (StringIndexOutOfBoundsException s){
          logger.error(s.toString());
      }

      try {
          //请求类名和方法名不为空走下面的操作，为空结束请求
          if ("" !=  annotation && "" != method){
              logger.debug(url +"：请求开始处理...");
              //获取项目下所有使用了@Controller的类
              List<Class<?>> classList = ClassHelper.getControllerListClass();
              //循环判断注解的属性值与路由的属性值
              for (Class<?> classes: classList) {
                  Controller mapAnnotation = classes.getAnnotation(Controller.class);
                  String value = mapAnnotation.value();
                  //相同匹配成功执行方法
                  if (annotation.equals(value)) {
                    try {
                      // 使用反射机制获取在本类中声明了的方法
                      Method method2 = classes.getDeclaredMethod(method, Context.class);
                      // 执行方法
                      logger.debug(url + "请求开始执行" + classes + "." + method + "方法....");
                      ClassHelper.invokeMethod2(classes, method2, (Object)context);
                    }catch (Exception nosm){
                      logger.error(nosm.toString());
                      System.out.println(nosm.toString());
                      // 执行方法
                      logger.debug(url + "请求执行" + classes + "." + method + "方法异常....");
                    }
                    break;
                  }
              }
          }else{
              logger.debug(url + "：请求路由异常...");
          }
      }catch (NullPointerException nu){
          logger.error(nu.toString());
      }
      
  }
  
  /**
   * 静态资源处理 --- 静态资源不处理含有中文地址名的资源请求
   * @param req
   * @param resp
   * @param context
   * @throws IOException 
   * @throws FileNotFoundException 
   */
  public void staticRequest(HttpServletRequest req, HttpServletResponse resp, Context context) throws Exception {
    context.setHttpServletRequest(req);
    context.setHttpServletResponse(resp);
    
    //统一文件分隔符并且处理路径
    String path = req.getSession().getServletContext().getRealPath("");
    String url = BaseUtil.pathSeparator(req.getRequestURI().substring(1));
    url = url.substring(url.indexOf(File.separator) + 1);
    String pathName = BaseUtil.pathSeparator(path + url);
    
    //根据路径获取文件
    File file = new File(pathName);
    
    //判断文件是否存在，存在直接输出不存在输出404
    if (!file.exists()) {
      
      String response = "<!DOCTYPE html><html lang=en><meta charset=utf-8>\r\n" + 
          "  <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">\r\n" + 
          "  <title>Error 404 (Not Found)!!!</title>\r\n" + 
          "  <style>\r\n" + 
          "    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}\r\n" + 
          "  </style>\r\n" + 
          "  <p><b>404 error.</b> <ins>Page Not Found.</ins>\r\n" + 
          "  <p>对不起，您请求的页面不存在、或已被删除、或暂时不可用</p>\r\n" + 
          "  <p>请检查您的请求路径是否正确</p>";
      
      context.setResponse(response);
    }else {
      
      context.setBinary(BaseUtil.fileParseBinary(file));
      
    }
  }
  
}
